package com.sl.ms.trade.service.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.sl.ms.trade.constant.Constants;
import com.sl.ms.trade.constant.TradingCacheConstant;
import com.sl.ms.trade.constant.TradingConstant;
import com.sl.ms.trade.entity.TradingEntity;
import com.sl.ms.trade.enums.PayChannelEnum;
import com.sl.ms.trade.enums.TradingEnum;
import com.sl.ms.trade.enums.TradingStateEnum;
import com.sl.ms.trade.handler.BeforePayHandler;
import com.sl.ms.trade.handler.HandlerFactory;
import com.sl.ms.trade.handler.NativePayHandler;
import com.sl.ms.trade.service.NativePayService;
import com.sl.ms.trade.service.QRCodeService;
import com.sl.ms.trade.service.TradingService;
import com.sl.transport.common.exception.SLException;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.concurrent.TimeUnit;

/**
 * @author wjh
 * @create 2023-09-22 13:46
 */
@Service
@Slf4j
public class NativePayServiceImpl implements NativePayService {
    
    @Resource
    private TradingService tradingService;
    
    @Resource
    private BeforePayHandler beforePayHandler;
    
    @Resource
    private RedissonClient redissonClient;

    @Resource
    private QRCodeService qrCodeService;

    @Override
    public String queryQrCodeUrl(Long tradingOrderNo) {
        TradingEntity tradingEntity = tradingService.findTradByTradingOrderNo(tradingOrderNo);
        if (ObjectUtil.equal(tradingEntity.getTradingState(), TradingStateEnum.YJS)) {
            //如果已经结算成功了，不返回二维码
            throw new SLException(TradingEnum.TRADING_STATE_SUCCEED);
        }
        return tradingEntity.getQrCode();
    }

    @Override
    public TradingEntity createDownLineTrading(TradingEntity tradingEntity) {
        //交易前置，检查交易参数
        Boolean flag = beforePayHandler.checkCreateTrading(tradingEntity);
        if (!flag) {
            throw new SLException(TradingEnum.CONFIG_ERROR);
        }
        tradingEntity.setTradingType(TradingConstant.TRADING_TYPE_FK);
        tradingEntity.setEnableFlag(Constants.YES);
        //对交易单进行加锁
        Long productOrderNo = tradingEntity.getProductOrderNo();
        String key = TradingCacheConstant.CREATE_PAY + productOrderNo;
        //获取公平锁
        RLock fairLock = redissonClient.getFairLock(key);
        try {
            if (fairLock.tryLock(5, TimeUnit.SECONDS)) {
                //交易前置处理：幂等性处理
                beforePayHandler.idempotentCreateTrading(tradingEntity);
                //调用不同的支付渠道进行处理
                PayChannelEnum payChannel = PayChannelEnum.valueOf(tradingEntity.getTradingChannel());
                NativePayHandler nativePayHandler = HandlerFactory.get(payChannel, NativePayHandler.class);
                assert nativePayHandler != null;
                nativePayHandler.createDownLineTrading(tradingEntity);
                //生成统一收款二维码
                String placeOrderMsg = tradingEntity.getPlaceOrderMsg();
                String qrCode = this.qrCodeService.generate(placeOrderMsg,payChannel);
                tradingEntity.setQrCode(qrCode);
                //新增或更新交易数据
                flag = tradingService.saveOrUpdate(tradingEntity);
                if (!flag) {
                    throw new SLException(TradingEnum.SAVE_OR_UPDATE_FAIL);
                }
                return tradingEntity;
            }
            throw new SLException(TradingEnum.NATIVE_PAY_FAIL);
        } catch (InterruptedException e) {
            log.error("统一收单线下交易预创建异常:{}", ExceptionUtil.stacktraceToString(e));
            throw new SLException(TradingEnum.NATIVE_QUERY_FAIL);
        } finally {
            fairLock.unlock();
        }

    }
}
